package cn.itcast.hotel.service.impl;

import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
     @Autowired
     private RestHighLevelClient client;

    @Override
    public PageResult search(RequestParams params) {

            SearchRequest request=new SearchRequest("hotel");
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            String key = params.getKey();
            if(StringUtils.isNotBlank(key)){
                boolQuery.must(QueryBuilders.matchQuery("all",key));
            }else{
               boolQuery.must(QueryBuilders.matchAllQuery());
            }
            if(StringUtils.isNotBlank(params.getBrand())){
               boolQuery.filter(QueryBuilders.termQuery("brand",params.getBrand()));
            }
            if(StringUtils.isNotBlank(params.getCity())){
            boolQuery.filter(QueryBuilders.termQuery("city",params.getCity()));
        }
            if(StringUtils.isNotBlank(params.getStarName())){
            boolQuery.filter(QueryBuilders.termQuery("starName",params.getStarName()));
        }
            if(params.getMinPrice() != null && params.getMaxPrice() != null){
             boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
            }
        String location = params.getLocation();
        if(StringUtils.isNotBlank(location)){
                request.source().sort(SortBuilders.geoDistanceSort("location", new GeoPoint(location)).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));
            }
            request.source().query(boolQuery);
            Integer page = params.getPage();
            Integer size = params.getSize();
            request.source().from((page-1)*size).size(size);
        try {
            SearchResponse response  = client.search(request, RequestOptions.DEFAULT);
            long total = response.getHits().getTotalHits().value;
            SearchHit[] hits = response.getHits().getHits();
            List<HotelDoc> hotelDocList=new ArrayList();
            for (SearchHit hit : hits) {
                String json = hit.getSourceAsString();
                HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
                Object[] sortValues = hit.getSortValues();
                if(sortValues.length>0){
                    hotelDoc.setDistance(sortValues[0]);
                }
                hotelDocList.add(hotelDoc);
            }
            return PageResult.builder().total(total).hotels(hotelDocList).build();
        } catch (IOException e) {
          log.error("serach error message:{}",e.getMessage());
        }
       
            return new PageResult();
    }

}
